/*
 * Copyright 2017 Baiyyy
 * @(#)TempUploadService.java
 */

package com.byyy.ccts.modules.cc.service.impl;

import com.byyy.ccts.core.base.ILogBase;
import com.byyy.ccts.core.common.service.impl.CommonServiceImpl;
import com.byyy.ccts.core.utils.CacheUtils;
import com.byyy.ccts.extend.zx.entity.Record;
import com.byyy.ccts.extend.zx.service.IRecordService;
import com.byyy.ccts.modules.cc.Global;
import com.byyy.ccts.modules.cc.entity.ccts.*;
import com.byyy.ccts.modules.cc.enums.PsStateEnum;
import com.byyy.ccts.modules.cc.enums.UploadFlagEnum;
import com.byyy.ccts.modules.cc.mapper.PsZcdMapper;
import com.byyy.ccts.modules.cc.mapper.PsZcdMxMapper;
import com.byyy.ccts.modules.cc.mapper.TempUploadInfoMapper;
import com.byyy.ccts.modules.cc.rmi.IUploadService;
import com.byyy.ccts.modules.cc.service.*;
import com.byyy.ccts.modules.sys.Constants;
import com.byyy.ccts.modules.sys.entity.Dict;
import com.byyy.ccts.modules.sys.service.IDictService;
import com.byyy.ccts.modules.sys.service.IParamService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.rmi.Naming;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by DELL on 2018-6-12.
 */
@Transactional
@Service("tempUploadService")
public class TempUploadService extends CommonServiceImpl<TempUploadInfoMapper, VWTempUploadInfo> implements ITempUploadService, ILogBase {

    @Autowired
    private IHumitureService humitureService;

    @Autowired
    private ICouvenseService couvenseService;

    @Autowired
    private IChillCarService chillCarService;

    @Autowired
    private IPsZcdService psZcdHzService;

    @Autowired
    private PsZcdMxMapper psZcdMxMapper;

    @Autowired
    private PsZcdMapper psZcdMapper;

    @Autowired
    private IDictService dictService;

    @Autowired
    private DataSourceTransactionManager transactionManager;

    @Autowired
    private IParamService paramService;

//    @Autowired
//    private IRecordService recordService;

    /**
     * 温度上传任务处理
     * jdbc:ucanaccess://\\172.16.1.89\db\DB.accdb;jackcessOpener=com.byyy.ccts.core.utils.CryptCodecOpenerUtils
     * 1.获取需要上传的装车单号，设备号，开始时间，结束时间
     * 2.根据设备号，开始时间，结束时间查询冷链温度记录
     * 3.查询CDPZ表，获取设备属性，然后将数据整合写入Record表中
     */
    @Override
    public void tempUpload() {
        String useZxChillcar = paramService.getValueByCode("USE_ZX_CHILLCAR");
        this.convenseTemperatureUpload();
        if (!Constants.Y.equals(useZxChillcar)) {
            this.chillCarTemperatureUpload();
        }
    }

    /**
     * 保温箱温度上传
     */
    private void convenseTemperatureUpload() {
        // 定义变量
        PsZcdHz zcdHz = null;
        List<TSHumiture> humitures = null;
        List<VWTempUploadInfo> convenseUploadInfos = null;
        List<String> chillCarList = null;
        List datas = null;

        // 找到尚未上传的保温箱信息,每次只查一条装车单
        convenseUploadInfos = this.baseMapper.queryConvenseUploadInfo();
        if (convenseUploadInfos == null || convenseUploadInfos.size() < 1) {
            return;
        }

        // 首先将装车单状态修改为上传中
        zcdHz = this.psZcdHzService.selectById(convenseUploadInfos.get(0).getZcdNo());
        // 开启新事务，将状态更新，如果在同一个事务中，因RMI执行时间过长导致数据不会写入数据库，下次再执行同一单时，会造成锁表状态
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
        zcdHz.setWdCsFlag(UploadFlagEnum.上传中.getValue());
        this.psZcdHzService.updateById(zcdHz);
        transactionManager.commit(status);

        // 一条条数据的处理吧，以装车单下的冷藏箱为单位进行处理
        try {
            for (VWTempUploadInfo temp : convenseUploadInfos) {
                humitures = this.humitureService.queryDeviceTempByTimeUpload(Arrays.asList(temp.getSbSn()), temp.getWdBeginDate(), temp.getWdEndDate());
                if (humitures == null || humitures.size() < 1) {
                    // 如果没有查询到温度数据，即因为特殊情况，比如客户要求比较严格需要重新发货，所以此单不再记录温度的情况,不用管，继续走
                    continue;
                }

                // 整合数据，写入Record表
                datas = this.generateRecordForBox(temp, humitures);
                this.insertRecord(datas, temp.getCangku());
            }

            // 最后将装车单状态修改为上传完毕
            zcdHz.setWdCsFlag(UploadFlagEnum.已上传.getValue());
            this.psZcdHzService.updateById(zcdHz);
        }
        catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 冷藏车温度上传
     */
    private void chillCarTemperatureUpload() {
        // 定义变量
        boolean isChillCarOver = true;
        List<String> chillCarList = null;
        List<VWTempUploadInfo> uploadInfos = null;
        List<PsZcdHz> psZcdHzList = null;
        List datas = null;
        List<TSHumiture> pointOneHumitures = null;
        List<TSHumiture> pointTwoHumitures = null;

        // 再上传冷藏车单据
        chillCarList = this.psZcdMxMapper.selectNotYetUploadedChillCar();
        if (chillCarList == null || chillCarList.size() < 1) {
            return;
        }
        for (String temp : chillCarList) {
            isChillCarOver = true;
            // 首先判断该冷藏车内的所有未上传的单据是否都已经完成
            psZcdHzList = this.psZcdMapper.queryNotYetUploadChillCarBill(temp);
            if (psZcdHzList == null || psZcdHzList.size() < 1) {
                continue;
            }
            // 如果冷藏车关联的装车单状态还有2:已激活的，说明没有全部完成
            for (PsZcdHz zcdHz : psZcdHzList) {
                if (PsStateEnum.激活关联.getValue().equals(zcdHz.getState())) {
                    isChillCarOver = false;
                    break;
                }
            }
            // 冷藏车内的单据没有全部完成，就继续下一个冷藏车
            if (!isChillCarOver) {
                continue;
            }
            // 如果冷藏车内的单据全部完成，则查询最早开始时间段到最晚开始时间段，全部完成，应该会有这个信息
            // 可能会存在，比如以前遗留的单据没有上传成功的现象，然后单据的冷藏车以及测点1和测点2都一致的情况，会上传多余的信息
            uploadInfos = this.baseMapper.queryChillCarUploadInfo(temp);
            for (VWTempUploadInfo uploadInfo : uploadInfos) {
                pointOneHumitures = this.humitureService.queryDeviceTempByTime(Arrays.asList(uploadInfo.getPointone()), uploadInfo.getWdBeginDate(), uploadInfo.getWdEndDate());
                pointTwoHumitures = this.humitureService.queryDeviceTempByTime(Arrays.asList(uploadInfo.getPointtwo()), uploadInfo.getWdBeginDate(), uploadInfo.getWdEndDate());
                // 整合数据，写入Record表
                datas = this.generateRecordForCar(uploadInfo, pointOneHumitures, pointTwoHumitures);
                this.insertRecord(datas, uploadInfo.getCangku());
                // 更新装车单状态
                this.psZcdMapper.updateUploadStateInCar(temp, uploadInfo.getWdBeginDate());
            }

        }
    }

    /**
     * 生成保温箱上传数据
     *
     * @param tempUploadInfo
     * @param humitures
     * @return
     */
    private List generateRecordForBox(VWTempUploadInfo tempUploadInfo, List<TSHumiture> humitures) {
        // 定义变量
        Object[] objs = null;
        String kfsx = null;
        TACouvense box = null;
        List ret = new ArrayList<>();
        List<TACouvense> boxList = null;
        List<Dict> dicts = null;

        // 获取箱子列表
        boxList = (List<TACouvense>) CacheUtils.get(Global.KEY_COUVENSE_LIST);
        if (boxList == null || boxList.size() < 1) {
            boxList = this.couvenseService.selectList(null);
            CacheUtils.put(Global.KEY_COUVENSE_LIST, boxList);
        }
        for (TACouvense temp : boxList) {
            if (temp.getId().equals(tempUploadInfo.getBoxSn())) {
                box = temp;
                break;
            }
        }

        // 获取箱子属性
        dicts = (List<Dict>) CacheUtils.get(Global.KEY_BOXATTR_LIST);
        if (dicts == null || dicts.size() < 1) {
            dicts = this.dictService.selectDictUsedListByGCode("boxAttr", null);
            CacheUtils.put(Global.KEY_BOXATTR_LIST, dicts);
        }
        for (Dict temp : dicts) {
            if (box.getAttr().equals(temp.getValue())) {
                kfsx = temp.getLabel();
                break;
            }
        }

        for (TSHumiture temp : humitures) {
            objs = new Object[]{
                    box.getNo(), box.getMeasurepoint(),
                    temp.getTemperature(), 0, temp.getCollectTime(),
                    kfsx, "0", "0",
                    temp.getTemperature(), 0,
            };
            ret.add(objs);
        }
        return ret;
    }

    /**
     * 生成冷藏车上传数据
     *
     * @param tempUploadInfo
     * @param pointOneHumitures
     * @param pointTwoHumitures
     * @return
     */
    private List generateRecordForCar(VWTempUploadInfo tempUploadInfo, List<TSHumiture> pointOneHumitures, List<TSHumiture> pointTwoHumitures) {
        // 定义变量
        Object[] objs = null;
        String wzName = null;
        TAChillCar car = null;
        List ret = new ArrayList<>();
        List<TAChillCar> carList = null;

        // 获取冷藏车列表
        carList = (List<TAChillCar>) CacheUtils.get(Global.KEY_CHILLCAR_LIST);
        if (carList == null || carList.size() < 1) {
            carList = this.chillCarService.selectList(null);
            CacheUtils.put(Global.KEY_CHILLCAR_LIST, carList);
        }
        for (TAChillCar temp : carList) {
            if (temp.getId().equals(tempUploadInfo.getBoxSn())) {
                car = temp;
                wzName = temp.getPlateNum();
                break;
            }
        }

        for (TSHumiture temp : pointOneHumitures) {
            objs = new Object[]{
                    wzName, car.getMeasurepointOne(),
                    temp.getTemperature(), 0, temp.getCollectTime(),
                    "车载", "0", "0",
                    temp.getTemperature(), 0,
            };
            ret.add(objs);
        }

        for (TSHumiture temp : pointTwoHumitures) {
            objs = new Object[]{
                    wzName, car.getMeasurepointTwo(),
                    temp.getTemperature(), 0, temp.getCollectTime(),
                    "车载", "0", "0",
                    temp.getTemperature(), 0,
            };
            ret.add(objs);
        }
        return ret;
    }

    /**
     * 批量插入记录
     * @param records
     */
    private void insertRecord(List<Object[]> records, String cangku) {
        try {
            IUploadService uploadService = null;
            switch (cangku) {
                case "QDC":
//                    this.recordService.insertBatch(this.conv2Record(records));
                    break;
                case "CK099009":
//                    uploadService = (IUploadService) Naming.lookup(Global.RMI_UPLOAD_SERVICE_CK099009);
//                    uploadService.upload(records);
                    break;
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 将Humiture转为Record
     * @param humitureList
     * @return
     */
    private List<Record> conv2Record(List<Object[]> humitureList) {
        List<Record> recordList = new ArrayList<>();
        Record record = null;

        for (Object[] objs : humitureList) {
            record = new Record();
            record.setWzName((String) objs[0]);
            record.setIpAddr((String) objs[1]);
            record.setWdz((Float) objs[2]);
            record.setSdz((Integer) objs[3]);
            record.setDt((Timestamp) objs[4]);
            record.setKfsx((String) objs[5]);
            record.setSjwdz((Float) objs[8]);
            record.setSjsdz((Integer) objs[9]);
            recordList.add(record);
        }

        return recordList;
    }

}
